//
// Created by 215609 on 2024/8/17.
//


#include "HWCoderPlayer.h"
void av_log_callback(void*ptr, int level, const char* fmt, va_list vl) {
    va_list vl2;
    char line[1024] = {0};
    static int print_prefix = 1;
    va_copy(vl2, vl);
    av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
    va_end(vl2);
    LOGCATI("FFMPEG: %s", line);
}
void HWCoderPlayer::init(JNIEnv *jniEnv, jobject obj, char *url, int renderType, jobject surface) {

    av_log_set_level(AV_LOG_DEBUG);
    av_log_set_callback(av_log_callback);
    strcpy(m_Url,url);
    m_ANativeWindow= ANativeWindow_fromSurface(jniEnv, surface);

    m_VideoPacketQueue=new AVPacketQueue();
    m_AudioPacketQueue=new AVPacketQueue();

    m_VideoPacketQueue->Start();
    m_AudioPacketQueue->Start();

    jniEnv->GetJavaVM(&m_JavaVM);
    m_JavaObj = jniEnv->NewGlobalRef(obj);
}

int HWCoderPlayer::InitDecoder() {
    int result = -1;
    do {
        //1.创建封装格式上下文
        m_AVFormatContext = avformat_alloc_context();
        //2.打开文件
        if (avformat_open_input(&m_AVFormatContext, m_Url, nullptr, nullptr) != 0) {
            LOGCATE("HWCodecPlayer::InitDecoder avformat_open_input fail.");
            break;
        }

        if (avformat_find_stream_info(m_AVFormatContext, nullptr)<0){
            LOGCATE("HWCodecPlayer::InitDecoder avformat_find_stream_info fail.");
            break;
        }

        AVCodec *videoCodec= nullptr,*audioCodec= nullptr;

        m_VideoStreamIdx = av_find_best_stream(m_AVFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, &videoCodec, 0);
        if(videoCodec == nullptr) {
            LOGCATE("HWCodecPlayer::InitDecoder video codec not found.");
            break;
        }

        m_AudioStreamIdx = av_find_best_stream(m_AVFormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &audioCodec, 0);
        if(audioCodec == nullptr) {
            LOGCATE("HWCodecPlayer::InitDecoder audio codec not found.");
            break;
        }

        if(m_AudioStreamIdx * m_VideoStreamIdx < 0) {
            LOGCATE("HWCodecPlayer::InitDecoder audio or vide stream not found. [m_AudioStreamIdx, m_VideoStreamIdx]=[%d, %d]", m_AudioStreamIdx, m_VideoStreamIdx);
            break;
        }


        m_VideoCodecCtx= avcodec_alloc_context3(videoCodec);
        if(m_VideoCodecCtx) {
            avcodec_parameters_to_context(m_VideoCodecCtx,m_AVFormatContext->streams[m_VideoStreamIdx]->codecpar);
            ////实时帧率。
            m_FrameRate =m_AVFormatContext->streams[m_VideoStreamIdx]->r_frame_rate;
        }


        AVDictionary *pAVDictionary = nullptr;
        av_dict_set(&pAVDictionary, "buffer_size", "1024000", 0);
        av_dict_set(&pAVDictionary, "stimeout", "20000000", 0);
        av_dict_set(&pAVDictionary, "max_delay", "30000000", 0);
        av_dict_set(&pAVDictionary, "rtsp_transport", "tcp", 0);
        result= avcodec_open2(m_VideoCodecCtx,videoCodec,&pAVDictionary);
        if(result < 0) {
            LOGCATE("HWCodecPlayer::InitDecoder avcodec_open2 videoCodec fail. result=%d", result);
            break;
        }


        m_AudioCodecCtx= avcodec_alloc_context3(audioCodec);
        if (m_AVFormatContext){
            avcodec_parameters_to_context(m_AudioCodecCtx,m_AVFormatContext->streams[m_AudioStreamIdx]->codecpar);
        }

        result= avcodec_open2(m_AudioCodecCtx,audioCodec,&pAVDictionary);
        if(result < 0) {
            LOGCATE("HWCodecPlayer::InitDecoder avcodec_open2 audioCodec fail. result=%d", result);
            break;
        }
//        AVBitStreamFilter  *mAVBitStreamFilter= av_bsf_get_by_name("h264_mp4toannexb");
        m_Bsfc = av_bitstream_filter_init("h264_mp4toannexb");
        if(m_Bsfc == nullptr) {
            result = -1;
            LOGCATE("HWCodecPlayer::InitDecoder av_bitstream_filter_init(\"h264_mp4toannexb\") fail.");
            break;
        }

        bool isAttach = false;
        JNIEnv *env = GetJNIEnv(&isAttach);

        m_MediaExtractor= AMediaExtractor_new();


    }while(false);


}

JNIEnv *HWCoderPlayer::GetJNIEnv(bool *isAttach) {
    JNIEnv *env;
    int status;
    if (nullptr == m_JavaVM) {
        LOGCATE("HWCodecPlayer::GetJNIEnv m_JavaVM == nullptr");
        return nullptr;
    }
    *isAttach = false;
    status = m_JavaVM->GetEnv((void **)&env, JNI_VERSION_1_4);
    if (status != JNI_OK) {
        status = m_JavaVM->AttachCurrentThread(&env, nullptr);
        if (status != JNI_OK) {
            LOGCATE("HWCodecPlayer::GetJNIEnv failed to attach current thread");
            return nullptr;
        }
        *isAttach = true;
    }
    return env;

}
void HWCoderPlayer::DeMuxThreadProc(HWCoderPlayer *player) {

    do {
        if (player->InitDecoder()) {

        }
    }while(false);


}

void HWCoderPlayer::Play() {
    if (m_DeMuxThread== nullptr){
        m_DeMuxThread=new thread(DeMuxThreadProc,this);

    }


}
